# 1. 导入依赖
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from utils.LogicRegression.LogicRegressionUtils import LogicRegressionUtils


# 2. 加载数据集
init_data = pd.read_csv("../static/data/iris.csv")

iris_type = ["SETOSA", "VERSICOLOR", "VIRGINICA"]
input_x = "petal_length"
input_y = "petal_width"

# 3. 展示初始数据
for type in iris_type:
    plt.scatter(init_data[input_x][init_data["class"] == type],
                init_data[input_y][init_data["class"] == type],
                label=type)

plt.xlabel(input_x)
plt.ylabel(input_y)
plt.legend()
plt.show()

# 4. 调用逻辑回归算法,训练数据
num_iterations = 10000
data = init_data[["petal_length", "petal_width"]].values.reshape(-1,2)
labels = init_data["class"].values.reshape(-1,1)
logistic_regression = LogicRegressionUtils(data, labels,normalize_data=False)

loss_histories = logistic_regression.train(num_iterations)
unique_labels = logistic_regression.unique_labels

# 5. 展示损失函数变化图(_*3矩阵)
plt.plot(loss_histories[0], label=unique_labels[0])
plt.plot(loss_histories[1], label=unique_labels[1])
plt.plot(loss_histories[2], label=unique_labels[2])
plt.xlabel("Iteration")
plt.ylabel("Loss")
plt.legend()
plt.show()

# 6. 计算准确率
predicted_labels = logistic_regression.predict_label(data)
accuracy = np.sum(predicted_labels == labels.flatten()) / labels.shape[0] * 100
print("Accuracy: ", accuracy, "%")

# 7. 决策边界
x_min, x_max = init_data[input_x].min() , init_data[input_x].max()
y_min, y_max = init_data[input_y].min() , init_data[input_y].max()
num_points = 100
x_points, y_points = np.linspace(x_min, x_max, num_points), np.linspace(y_min, y_max, num_points)
prediction_grid_SETOSA = np.zeros((num_points, num_points))
prediction_grid_VERSICOLOR = np.zeros((num_points, num_points))
prediction_grid_VIRGINICA = np.zeros((num_points, num_points))

for i,i_val in enumerate(x_points):
    for j,j_val in enumerate(y_points):
        prediction_label = logistic_regression.predict_label(np.array([[i_val, j_val]]))[0]
        if prediction_label == 'SETOSA':
            prediction_grid_SETOSA[i][j] = 1
        elif prediction_label == 'VERSICOLOR':
            prediction_grid_VERSICOLOR[i][j] = 1
        else:
            prediction_grid_VIRGINICA[i][j] = 1



# 8. 展示决策边界
plt.contour(x_points.flatten(), y_points.flatten(), prediction_grid_SETOSA)
plt.contour(x_points.flatten(), y_points.flatten(), prediction_grid_VERSICOLOR)
plt.contour(x_points.flatten(), y_points.flatten(), prediction_grid_VIRGINICA)
for type in iris_type:
    plt.scatter(init_data[input_x][init_data["class"] == type],
                init_data[input_y][init_data["class"] == type],
                label=type)
plt.xlabel(input_x)
plt.ylabel(input_y)
plt.legend()
plt.show()